#include "config.h"

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <dirent.h>
#include <ctype.h>
#include <libgen.h>

#define DBG_SUBSYS S_LIBINTERFACE

#include "configure.h"
#include "env.h"
#include "adt.h"
#include "net_table.h"
#include "lichstor.h"
#include "cluster.h"
#include "metadata.h"
#include "lich_md.h"
#include "storage.h"
#include "volume.h"
#include "lichbd.h"
#include "license.h"
#include "md_map.h"
#include "net_global.h"
#include "dbg.h"

#define WRITEBACK_SEG_SIZE  (8 * M2B)

#define __GET_WRITEBACK_SIZE__(size) (_align_down((size * 8) / 10, PAGE_SIZE))
#define __GET_WRITEBACK_MD_TOTAL__(size) (_align_down(size / 10, PAGE_SIZE))
#define __GET_WRITEBACK_SEG_LEN__(size) WRITEBACK_SEG_SIZE
#define __GET_WRITEBACK_SEG_COUNT__(size) (__GET_WRITEBACK_SIZE__(size) / __GET_WRITEBACK_SEG_LEN__(size))
#define __GET_WRITEBACK_SEG_MD_COUNT__(size) (__GET_WRITEBACK_SEG_LEN__(size) / 4096)
#define __GET_WRITEBACK_SEG_MD_SIZE__(size) (__GET_WRITEBACK_SEG_MD_COUNT__(size) * sizeof(wb_md_t))
#define __GET_WRITEBACK_MD_HEAD__(size) (_align_down((size * 128) / (10 * 1024), PAGE_SIZE))
#define __GET_WRITEBACK_MD_OFFSET__(size) __GET_WRITEBACK_MD_HEAD__(size)

typedef struct {
        chkid_t chkid;
        //uint64_t fingerprint;
        int size;
        int offset;
        uint32_t data_crc;
        uint64_t seg_offset;
        //uint32_t meta_crc;
} wb_md_t;

void __unit_test_wb(uint64_t size)
{
        printf("size:%.2fG\n", (double)size/G2B);
        printf("    __GET_WRITEBACK_SIZE__(size):%.2fG\n", (double)__GET_WRITEBACK_SIZE__(size)/G2B);
        printf("    __GET_WRITEBACK_MD_TOTAL__(size):%.2fG\n", (double)__GET_WRITEBACK_MD_TOTAL__(size)/G2B);
        printf("    __GET_WRITEBACK_SEG_LEN__(size):%.2fM\n", (double)__GET_WRITEBACK_SEG_LEN__(size)/M2B);
        printf("    __GET_WRITEBACK_SEG_COUNT__(size):%ld\n", __GET_WRITEBACK_SEG_COUNT__(size));
        printf("    __GET_WRITEBACK_SEG_MD_COUNT__(size):%ld\n", __GET_WRITEBACK_SEG_MD_COUNT__(size));
        printf("    __GET_WRITEBACK_SEG_MD_SIZE__(size):%.2fK\n", (double)__GET_WRITEBACK_SEG_MD_SIZE__(size)/K2B);
        printf("    __GET_WRITEBACK_MD_HEAD__(size):%.2fM\n", (double)__GET_WRITEBACK_MD_HEAD__(size)/M2B);
        printf("    __GET_WRITEBACK_MD_OFFSET__(size):%ld\n", __GET_WRITEBACK_MD_OFFSET__(size));
        printf("    __GET_WRITEBACK_SEG_MD_SIZE__(size) * __GET_WRITEBACK_SEG_COUNT__(size):%.2fG\n",
                        (double)__GET_WRITEBACK_SEG_MD_SIZE__(size) * __GET_WRITEBACK_SEG_COUNT__(size)/G2B);
}

int unit_test_wb(const char *func)
{
        (void) func;

        __unit_test_wb(1 * G2B);
        __unit_test_wb(10 * G2B);
        __unit_test_wb(100 * G2B);
        __unit_test_wb(1000 * G2B);

        return 0;
}
